library(Seurat)
library(scHolography)
library(dplyr)
scHolography.obj <- readRDS("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin/scHolography.obj_new.rds")
sup.with.more.basal <- which(rowSums(scHolography.obj$adj.mtx[which(scHolography.obj$scHolography.sc$celltype%in%"Suprabasal"),which(scHolography.obj$scHolography.sc$celltype%in%"Basal")])>=min(boxplot.stats(rowSums(scHolography.obj$adj.mtx[which(scHolography.obj$scHolography.sc$celltype%in%"Suprabasal"),which(scHolography.obj$scHolography.sc$celltype%in%"Basal")]))$out)
)
sup.with.more.basal.names <- (colnames(scHolography.obj$scHolography.sc)[which(scHolography.obj$scHolography.sc$celltype%in%"Suprabasal")])[sup.with.more.basal]
sup.with.less.basal.names <- (colnames(scHolography.obj$scHolography.sc)[which(scHolography.obj$scHolography.sc$celltype%in%"Suprabasal")])[-sup.with.more.basal]
scHolography.obj$scHolography.sc$suprabasal.sub <- as.character(scHolography.obj$scHolography.sc$celltype)
scHolography.obj$scHolography.sc$suprabasal.sub[sup.with.more.basal.names] <- "Transition_KC"
scHolography.obj$scHolography.sc$suprabasal.sub[sup.with.less.basal.names] <- "Differentiated_KC"
scHolography.obj$scHolography.sc$suprabasal.sub <-factor(as.character(scHolography.obj$scHolography.sc$suprabasal.sub ),levels = c("Basal", "Transition_KC", "Differentiated_KC","Endothelial", "Fibroblast","Smooth Muscle", "Lymphatic Endothelial","Schwann","Glandular Epithelium","Immune","Melanocyte"))
scHolography.obj$scHolography.sc <- SetIdent(scHolography.obj$scHolography.sc,value = "suprabasal.sub")
DefaultAssay(scHolography.obj$scHolography.sc) <- "RNA"
scHolography.obj$scHolography.sc <- ScaleData(scHolography.obj$scHolography.sc)
Centering and scaling data matrix
|
| | 0%
|
|====== | 4%
|
|============ | 9%
|
|================== | 13%
|
|======================== | 17%
|
|============================== | 22%
|
|==================================== | 26%
|
|========================================== | 30%
|
|================================================ | 35%
|
|====================================================== | 39%
|
|============================================================ | 43%
|
|================================================================== | 48%
|
|======================================================================== | 52%
|
|============================================================================== | 57%
|
|==================================================================================== | 61%
|
|========================================================================================== | 65%
|
|================================================================================================ | 70%
|
|====================================================================================================== | 74%
|
|============================================================================================================ | 78%
|
|================================================================================================================== | 83%
|
|======================================================================================================================== | 87%
|
|============================================================================================================================== | 91%
|
|==================================================================================================================================== | 96%
|
|==========================================================================================================================================| 100%
scHolographyPlot(scHolography.obj,color.by = "suprabasal.sub",palette = "Set3")
my.col <- c("#A6CEE3","#B96A59","#743A36")
scHolography.obj.sub<- scHolography.obj
scHolography.obj.sub$scHolography.sc <- subset(scHolography.obj.sub$scHolography.sc,cells=which(scHolography.obj.sub$scHolography.sc$suprabasal.sub%in%c("Basal", "Transition_KC", "Differentiated_KC")))
scHolography.obj.sub$scHolography.sc$suprabasal.sub <- droplevels(scHolography.obj.sub$scHolography.sc$suprabasal.sub)
scene = list(camera = list(eye = list(x = -1, z = 0, y = 2)))
fig1 <- scHolographyPlot(scHolography.obj.sub,color.by = "suprabasal.sub",color = my.col)%>% plotly::layout(scene = scene)
fig1
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_3rdDraft//sup.num.basal.vs.sup.neighbor.tiff", units="in", width=5, height=5, res=300)
ggplot(data = sup.epi.neighb, aes(x = n.suprabasal, y = n.basal)) +
geom_jitter(aes(color=type)) +
stat_cor(label.y = 30, size = 6) +theme_classic()+scale_color_manual(values = my.col[2:3])+
geom_smooth(method = "lm",
formula = y ~ x) +NoLegend()+xlab("# of Suprabasal Neighbors")+ylab("# of Basal Neighbors")+theme(axis.text = element_text(size = 15,face = "bold"),axis.text.x = element_text(angle = 45,hjust=1),axis.title=element_text(size = 15,face = "bold"))
dev.off()
null device
1
my_comparisons <- list( c("Basal", "Transition_KC"), c("Transition_KC", "Differentiated_KC") )
#tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//clusterDist.Basal.tiff", units="in", width=5, height=5, res=300)
scHolography::clusterDistanceBoxplot(scHolography.obj.sub,annotationToUse = "suprabasal.sub",query.cluster.list = c("Basal", "Transition_KC","Differentiated_KC"),reference.cluster = c("Basal"))+ggplot2::scale_fill_manual(values =my.col)+
geom_signif(comparisons = my_comparisons,test.args = list(size=5),map_signif_level = TRUE)+NoLegend()+theme(axis.text = element_text(size = 16,face = "bold"),axis.title.x = element_blank(),axis.title.y = element_text(size = 20,face = "bold") ,axis.text.x = element_text(angle = 45,hjust=1))
#dev.off()
mark.ba <- FindMarkers(scHolography.obj$scHolography.sc,ident.1 = "Transition_KC",ident.2 = "Basal" ,assay = "RNA")
| | 0 % ~calculating
|+ | 1 % ~01s
|++ | 2 % ~01s
|++ | 3 % ~01s
|+++ | 4 % ~01s
|+++ | 5 % ~01s
|++++ | 6 % ~01s
|++++ | 7 % ~01s
|+++++ | 8 % ~01s
|+++++ | 9 % ~01s
|++++++ | 10% ~01s
|++++++ | 11% ~01s
|+++++++ | 12% ~01s
|+++++++ | 13% ~01s
|++++++++ | 14% ~01s
|++++++++ | 15% ~01s
|+++++++++ | 16% ~01s
|+++++++++ | 17% ~01s
|++++++++++ | 18% ~01s
|++++++++++ | 19% ~01s
|+++++++++++ | 20% ~01s
|+++++++++++ | 21% ~01s
|++++++++++++ | 22% ~01s
|++++++++++++ | 23% ~01s
|+++++++++++++ | 24% ~01s
|+++++++++++++ | 26% ~01s
|++++++++++++++ | 27% ~01s
|++++++++++++++ | 28% ~01s
|+++++++++++++++ | 29% ~01s
|+++++++++++++++ | 30% ~01s
|++++++++++++++++ | 31% ~01s
|++++++++++++++++ | 32% ~01s
|+++++++++++++++++ | 33% ~01s
|+++++++++++++++++ | 34% ~01s
|++++++++++++++++++ | 35% ~01s
|++++++++++++++++++ | 36% ~01s
|+++++++++++++++++++ | 37% ~01s
|+++++++++++++++++++ | 38% ~01s
|++++++++++++++++++++ | 39% ~01s
|++++++++++++++++++++ | 40% ~01s
|+++++++++++++++++++++ | 41% ~01s
|+++++++++++++++++++++ | 42% ~01s
|++++++++++++++++++++++ | 43% ~01s
|++++++++++++++++++++++ | 44% ~01s
|+++++++++++++++++++++++ | 45% ~01s
|+++++++++++++++++++++++ | 46% ~01s
|++++++++++++++++++++++++ | 47% ~01s
|++++++++++++++++++++++++ | 48% ~01s
|+++++++++++++++++++++++++ | 49% ~01s
|+++++++++++++++++++++++++ | 50% ~01s
|++++++++++++++++++++++++++ | 51% ~01s
|+++++++++++++++++++++++++++ | 52% ~00s
|+++++++++++++++++++++++++++ | 53% ~00s
|++++++++++++++++++++++++++++ | 54% ~00s
|++++++++++++++++++++++++++++ | 55% ~00s
|+++++++++++++++++++++++++++++ | 56% ~00s
|+++++++++++++++++++++++++++++ | 57% ~00s
|++++++++++++++++++++++++++++++ | 58% ~00s
|++++++++++++++++++++++++++++++ | 59% ~00s
|+++++++++++++++++++++++++++++++ | 60% ~00s
|+++++++++++++++++++++++++++++++ | 61% ~00s
|++++++++++++++++++++++++++++++++ | 62% ~00s
|++++++++++++++++++++++++++++++++ | 63% ~00s
|+++++++++++++++++++++++++++++++++ | 64% ~00s
|+++++++++++++++++++++++++++++++++ | 65% ~00s
|++++++++++++++++++++++++++++++++++ | 66% ~00s
|++++++++++++++++++++++++++++++++++ | 67% ~00s
|+++++++++++++++++++++++++++++++++++ | 68% ~00s
|+++++++++++++++++++++++++++++++++++ | 69% ~00s
|++++++++++++++++++++++++++++++++++++ | 70% ~00s
|++++++++++++++++++++++++++++++++++++ | 71% ~00s
|+++++++++++++++++++++++++++++++++++++ | 72% ~00s
|+++++++++++++++++++++++++++++++++++++ | 73% ~00s
|++++++++++++++++++++++++++++++++++++++ | 74% ~00s
|++++++++++++++++++++++++++++++++++++++ | 76% ~00s
|+++++++++++++++++++++++++++++++++++++++ | 77% ~00s
|+++++++++++++++++++++++++++++++++++++++ | 78% ~00s
|++++++++++++++++++++++++++++++++++++++++ | 79% ~00s
|++++++++++++++++++++++++++++++++++++++++ | 80% ~00s
|+++++++++++++++++++++++++++++++++++++++++ | 81% ~00s
|+++++++++++++++++++++++++++++++++++++++++ | 82% ~00s
|++++++++++++++++++++++++++++++++++++++++++ | 83% ~00s
|++++++++++++++++++++++++++++++++++++++++++ | 84% ~00s
|+++++++++++++++++++++++++++++++++++++++++++ | 85% ~00s
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~00s
|++++++++++++++++++++++++++++++++++++++++++++ | 87% ~00s
|++++++++++++++++++++++++++++++++++++++++++++ | 88% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++ | 89% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++ | 90% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++ | 91% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++ | 92% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 93% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 94% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 95% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 96% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s
# VlnPlot(scHolography.obj$scHolography.sc,c("ITGB4","LAMB3","DST","COL17A1"),idents = c("Transition_KC","Differentiated_KC","Basal "),assay = "SCT",ncol = 2,cols = my.col)
# VlnPlot(scHolography.obj$scHolography.sc,c("FABP7","THEM5","KRT10","DSG1"),idents = c("Transition_KC","Differentiated_KC","Basal"),assay = "SCT",ncol = 2,cols = my.col)
VlnPlot(scHolography.obj$scHolography.sc,c("KRT5"),idents = c("Transition_KC","Differentiated_KC","Basal"),assay = "SCT", cols = my.col)+
geom_signif(comparisons = my_comparisons,test.args = list(size=5),map_signif_level = TRUE)+ylim(c(0,7))+NoLegend()+ theme(axis.title.x = element_blank(),axis.title.y = element_blank(),axis.text = element_text(size = 15,face = "bold"))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

epi.sub <- subset(scHolography.obj$scHolography.sc, cells = which(scHolography.obj$scHolography.sc@active.ident%in% c("Transition_KC","Differentiated_KC")))
DefaultAssay(epi.sub) <- "RNA"
DotPlot(epi.sub,features = c("HSPG2","COL17A1","PDGFA","ITGB1","ITGA2","COL7A1","ITGB4","LAMB3","DST",
"KRT1","KRT10","DSG1","EVPL","PERP", #keratinization
"PLA2G4F","STARD10","PLPP2","RORA","HMGCR","FABP7","DBI","THEM5","EPHX2","PTGS1","GSTA4" ),assay = "SCT")+viridis::scale_color_viridis()+ggplot2::coord_flip()+ theme(axis.text.x = element_text(angle = 45, hjust=1))
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//DotPlot.trans.vs.diff.tiff", units="in", width=3, height=10, res=300)
DotPlot(epi.sub,features = c(rownames(mark.sup %>%top_n(n = 10, wt = avg_log2FC) ),rownames(mark.sup %>%top_n(n = 10, wt = -avg_log2FC) )),assay = "SCT")+viridis::scale_color_viridis()+ggplot2::coord_flip()+ theme(axis.text.x = element_text(angle = 45, hjust=1))+theme(axis.title.x = element_blank(),axis.title.y = element_blank(),axis.text = element_text(size = 15,face = "bold"))+NoLegend()
dev.off()
epi.sub <- subset(scHolography.obj$scHolography.sc, cells = which(scHolography.obj$scHolography.sc@active.ident%in% c("Transition_KC","Basal")))
DefaultAssay(epi.sub) <- "RNA"
DotPlot(epi.sub,features = c("ANXA1","CLSTN1","DUSP6","PTPRZ1","MEF2A", #signal transduction
"COL17A1","PDGFA","ITGB1","COL4A5","COL7A1","ITGB4","LAMB3","DST", #extracellular matrix
"DSG1","KRT1","KRT10",
"NECTIN1","NECTIN4","CLDN4","CLDN1"
),assay = "SCT")+viridis::scale_color_viridis()+ggplot2::coord_flip()+ theme(axis.text.x = element_text(angle = 45, hjust=1))
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//DotPlot.trans.vs.basal.tiff", units="in", width=3, height=10, res=300)
DotPlot(epi.sub,features = c(rownames(mark.ba %>%top_n(n = 10, wt = avg_log2FC) ),rownames(mark.ba %>%top_n(n = 10, wt = -avg_log2FC) )),assay = "SCT")+viridis::scale_color_viridis()+ggplot2::coord_flip()+ theme(axis.text.x = element_text(angle = 45, hjust=1))+theme(axis.title.x = element_blank(),axis.title.y = element_blank(),axis.text = element_text(size = 15,face = "bold"))+NoLegend()
dev.off()
library(CellChat)
epi.sub <- subset(scHolography.obj$scHolography.sc, cells = which(scHolography.obj$scHolography.sc@active.ident%in% c("Transition_KC","Basal","Differentiated_KC")))
epi.sub$suprabasal.sub <- droplevels(epi.sub$suprabasal.sub )
cellchat.obj <- createCellChat(epi.sub,group.by = "suprabasal.sub",assay = "SCT")
CellChatDB <- CellChatDB.human
CellChatDB.use <- CellChatDB
cellchat.obj@DB <- CellChatDB.use
cellchat.obj <- subsetData(cellchat.obj)
cellchat.obj <- identifyOverExpressedGenes(cellchat.obj)
cellchat.obj <- identifyOverExpressedInteractions(cellchat.obj)
cellchat.obj <- computeCommunProb(cellchat.obj)
# Filter out the cell-cell communication if there are only few number of cells in certain cell groups
cellchat.obj <- filterCommunication(cellchat.obj, min.cells = 10)
cellchat.obj <- computeCommunProbPathway(cellchat.obj)
cellchat.obj <- aggregateNet(cellchat.obj)
library(RColorBrewer)
cellchat.obj <- netAnalysis_computeCentrality(cellchat.obj, slot.name = "netP")
my.sig <- c("LAMININ","THBS","DESMOSOME","NECTIN","NOTCH","EGF","NRG")
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//Epithelial.cellchat.out.tiff", units="in", width=9, height=6, res=300)
netAnalysis_signalingRole_heatmap(cellchat.obj, pattern = "outgoing",width = 9,height = 6,font.size = 15,color.heatmap = "YlOrRd",signaling =my.sig,color.use = my.col )
dev.off()
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//Epithelial.cellchat.in.tiff", units="in", width=9, height=6, res=300)
netAnalysis_signalingRole_heatmap(cellchat.obj, pattern = "incoming",width = 9,height = 6,font.size = 15,color.heatmap = "YlOrRd",signaling =my.sig,color.use = my.col )
dev.off()
Reactome_2022_high_diff <- read.delim("~/Library/CloudStorage/OneDrive-NorthwesternUniversity/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin/Reactome_2022_HIGH_in_diff_kc.txt", quote="")
Reactome_2022_high_diff.sub <- Reactome_2022_high_diff[1:5,]
Reactome_2022_high_diff.sub$Term <- unlist(lapply(Reactome_2022_high_diff.sub$Term , function(x) strsplit(x," R-HSA")[[1]][1]))
Reactome_2022_high_diff.sub$Term <- factor(Reactome_2022_high_diff.sub$Term,levels = rev(Reactome_2022_high_diff.sub$Term))
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//Reactome_2022_high_diff.tiff", units="in", width=6, height=6, res=300)
ggplot(data=Reactome_2022_high_diff.sub, aes(x=Term, y=-log(Adjusted.P.value))) +
geom_bar(stat="identity",fill=my.col[3]) + coord_flip()+theme_classic()+theme(axis.title.y = element_blank(),axis.text.y = element_blank(),axis.text = element_text(size = 15,face = "bold"),axis.title = element_text(size = 15,face = "bold"))
dev.off()
ggplot(data=Reactome_2022_high_diff.sub, aes(x=Term, y=-log(Adjusted.P.value))) +
geom_bar(stat="identity",fill=my.col[3]) + coord_flip()+theme_classic()+theme(axis.title.y = element_blank(),axis.text = element_text(size = 15,face = "bold"),axis.title = element_text(size = 15,face = "bold"))+geom_text(aes(label=Genes), y=c(0),hjust = 0,color="white", size=c(1.75,2.25,2.5,2.5,2.5))+theme(axis.title.y = element_blank())
### Run Reatome 2022 on genes with <0.05 adjusted p values in UpReg_in_Differentiated_KC_comp_w_Transition_KC.csv and UpReg_in_Transition_KC_comp_w_Basal.csv
Reactome_2022_high_trans <- read.delim("~/Library/CloudStorage/OneDrive-NorthwesternUniversity/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin/Reactome_2022_HIGH_in_trans.txt", quote="")
Reactome_2022_high_trans.sub <- Reactome_2022_high_trans[1:5,]
Reactome_2022_high_trans.sub$Term <- unlist(lapply(Reactome_2022_high_trans.sub$Term , function(x) strsplit(x," R-HSA")[[1]][1]))
Reactome_2022_high_trans.sub$Term <- factor(Reactome_2022_high_trans.sub$Term,levels = rev(Reactome_2022_high_trans.sub$Term))
tiff("~/OneDrive - Northwestern University/Northwestern/Yi Lab/Manuscript/Code_2ndDraft/Human Skin//Reactome_2022_high_trans.tiff", units="in", width=6, height=6, res=300)
ggplot(data=Reactome_2022_high_trans.sub, aes(x=Term, y=-log(Adjusted.P.value))) +
geom_bar(stat="identity",fill=my.col[2]) + coord_flip()+theme_classic()+theme(axis.title.y = element_blank(),axis.text.y = element_blank(),axis.text = element_text(size = 15,face = "bold"),axis.title = element_text(size = 15,face = "bold"))
dev.off()
ggplot(data=Reactome_2022_high_trans.sub, aes(x=Term, y=-log(Adjusted.P.value))) +
geom_bar(stat="identity",fill=my.col[2]) + coord_flip()+theme_classic()+theme(axis.title.y = element_blank(),axis.text = element_text(size = 15,face = "bold"),axis.title = element_text(size = 15,face = "bold"))+theme_classic()+geom_text(aes(label=Genes), y=c(0),hjust = 0,color="white", size=c(2.5,2.5,2.5,2.5,2.5))+theme(axis.title.y = element_blank())
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShzY0hvbG9ncmFwaHkpCmxpYnJhcnkoZHBseXIpCnNjSG9sb2dyYXBoeS5vYmogPC0gcmVhZFJEUygifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzJuZERyYWZ0L0h1bWFuIFNraW4vc2NIb2xvZ3JhcGh5Lm9ial9uZXcucmRzIikKCnN1cC53aXRoLm1vcmUuYmFzYWwgPC0gd2hpY2gocm93U3VtcyhzY0hvbG9ncmFwaHkub2JqJGFkai5tdHhbd2hpY2goc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MkY2VsbHR5cGUlaW4lIlN1cHJhYmFzYWwiKSx3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRjZWxsdHlwZSVpbiUiQmFzYWwiKV0pPj1taW4oYm94cGxvdC5zdGF0cyhyb3dTdW1zKHNjSG9sb2dyYXBoeS5vYmokYWRqLm10eFt3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRjZWxsdHlwZSVpbiUiU3VwcmFiYXNhbCIpLHdoaWNoKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjJGNlbGx0eXBlJWluJSJCYXNhbCIpXSkpJG91dCkKKQoKc3VwLndpdGgubW9yZS5iYXNhbC5uYW1lcyA8LSAoY29sbmFtZXMoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MpW3doaWNoKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjJGNlbGx0eXBlJWluJSJTdXByYWJhc2FsIildKVtzdXAud2l0aC5tb3JlLmJhc2FsXQpzdXAud2l0aC5sZXNzLmJhc2FsLm5hbWVzIDwtIChjb2xuYW1lcyhzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYylbd2hpY2goc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MkY2VsbHR5cGUlaW4lIlN1cHJhYmFzYWwiKV0pWy1zdXAud2l0aC5tb3JlLmJhc2FsXQoKc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2Mkc3VwcmFiYXNhbC5zdWIgPC0gYXMuY2hhcmFjdGVyKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjJGNlbGx0eXBlKQpzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRzdXByYWJhc2FsLnN1YltzdXAud2l0aC5tb3JlLmJhc2FsLm5hbWVzXSA8LSAiVHJhbnNpdGlvbl9LQyIKc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2Mkc3VwcmFiYXNhbC5zdWJbc3VwLndpdGgubGVzcy5iYXNhbC5uYW1lc10gPC0gIkRpZmZlcmVudGlhdGVkX0tDIgpzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRzdXByYWJhc2FsLnN1YiA8LWZhY3Rvcihhcy5jaGFyYWN0ZXIoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2Mkc3VwcmFiYXNhbC5zdWIgKSxsZXZlbHMgPSBjKCJCYXNhbCIsICJUcmFuc2l0aW9uX0tDIiwgIkRpZmZlcmVudGlhdGVkX0tDIiwiRW5kb3RoZWxpYWwiLCAiRmlicm9ibGFzdCIsIlNtb290aCBNdXNjbGUiLCAiTHltcGhhdGljIEVuZG90aGVsaWFsIiwiU2Nod2FubiIsIkdsYW5kdWxhciBFcGl0aGVsaXVtIiwiSW1tdW5lIiwiTWVsYW5vY3l0ZSIpKQoKc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MgPC0gU2V0SWRlbnQoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsdmFsdWUgPSAic3VwcmFiYXNhbC5zdWIiKSAKRGVmYXVsdEFzc2F5KHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjKSA8LSAiUk5BIgpzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyA8LSBTY2FsZURhdGEoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MpCnNjSG9sb2dyYXBoeVBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaixjb2xvci5ieSA9ICJzdXByYWJhc2FsLnN1YiIscGFsZXR0ZSA9ICJTZXQzIikKbXkuY29sIDwtIGMoIiNBNkNFRTMiLCIjQjk2QTU5IiwiIzc0M0EzNiIpCnNjSG9sb2dyYXBoeS5vYmouc3ViPC0gc2NIb2xvZ3JhcGh5Lm9iagpzY0hvbG9ncmFwaHkub2JqLnN1YiRzY0hvbG9ncmFwaHkuc2MgPC0gc3Vic2V0KHNjSG9sb2dyYXBoeS5vYmouc3ViJHNjSG9sb2dyYXBoeS5zYyxjZWxscz13aGljaChzY0hvbG9ncmFwaHkub2JqLnN1YiRzY0hvbG9ncmFwaHkuc2Mkc3VwcmFiYXNhbC5zdWIlaW4lYygiQmFzYWwiLCAiVHJhbnNpdGlvbl9LQyIsICJEaWZmZXJlbnRpYXRlZF9LQyIpKSkKc2NIb2xvZ3JhcGh5Lm9iai5zdWIkc2NIb2xvZ3JhcGh5LnNjJHN1cHJhYmFzYWwuc3ViIDwtIGRyb3BsZXZlbHMoc2NIb2xvZ3JhcGh5Lm9iai5zdWIkc2NIb2xvZ3JhcGh5LnNjJHN1cHJhYmFzYWwuc3ViKQoKCnNjZW5lID0gbGlzdChjYW1lcmEgPSBsaXN0KGV5ZSA9IGxpc3QoeCA9IC0xLCB6ID0gMCwgeSA9IDIpKSkKZmlnMSA8LSBzY0hvbG9ncmFwaHlQbG90KHNjSG9sb2dyYXBoeS5vYmouc3ViLGNvbG9yLmJ5ID0gInN1cHJhYmFzYWwuc3ViIixjb2xvciA9IG15LmNvbCklPiUgcGxvdGx5OjpsYXlvdXQoc2NlbmUgPSBzY2VuZSkKZmlnMQpwbG90bHk6Om9yY2EoZmlnMSwgImVwaXRoZWxpYWwuMy5sYXllcnMuc3ZnIix3aWR0aCA9IDcsaGVpZ2h0ID0gNSkKYGBgCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dwdWJyKQpuLmJhc2FsIDwtcm93U3VtcyhzY0hvbG9ncmFwaHkub2JqJGFkai5tdHhbd2hpY2goc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MkY2VsbHR5cGUlaW4lIlN1cHJhYmFzYWwiKSx3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRjZWxsdHlwZSVpbiUiQmFzYWwiKV0pCm4uc3VwcmFiYXNhbCA8LXJvd1N1bXMoc2NIb2xvZ3JhcGh5Lm9iaiRhZGoubXR4W3doaWNoKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjJGNlbGx0eXBlJWluJSJTdXByYWJhc2FsIiksd2hpY2goc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MkY2VsbHR5cGUlaW4lIlN1cHJhYmFzYWwiKV0pCnR5cGUgPC0gc2NIb2xvZ3JhcGh5Lm9iai5zdWIkc2NIb2xvZ3JhcGh5LnNjJHN1cHJhYmFzYWwuc3ViW2NvbG5hbWVzKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjKVt3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyRjZWxsdHlwZSVpbiUiU3VwcmFiYXNhbCIpIF1dCgpzdXAuZXBpLm5laWdoYiA8LSBkYXRhLmZyYW1lKG4uYmFzYWw9bi5iYXNhbCwgbi5zdXByYWJhc2FsPW4uc3VwcmFiYXNhbCwgdHlwZT10eXBlKQoKdGlmZigifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzNyZERyYWZ0Ly9zdXAubnVtLmJhc2FsLnZzLnN1cC5uZWlnaGJvci50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NSwgaGVpZ2h0PTUsIHJlcz0zMDApCmdncGxvdChkYXRhID0gc3VwLmVwaS5uZWlnaGIsIGFlcyh4ID0gbi5zdXByYWJhc2FsLCB5ID0gbi5iYXNhbCkpICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3I9dHlwZSkpICsKICBzdGF0X2NvcihsYWJlbC55ID0gMzAsIHNpemUgPSA2KSArdGhlbWVfY2xhc3NpYygpK3NjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteS5jb2xbMjozXSkrIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIAogICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4geCkgK05vTGVnZW5kKCkreGxhYigiIyBvZiBTdXByYWJhc2FsIE5laWdoYm9ycyIpK3lsYWIoIiMgb2YgQmFzYWwgTmVpZ2hib3JzIikrdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LGhqdXN0PTEpLGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvc3VwLm51bS5iYXNhbC5uZWlnaGJvci50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9MywgaGVpZ2h0PTUsIHJlcz0zMDApCmdncGxvdChkYXRhID0gc3VwLmVwaS5uZWlnaGIsIGFlcyh4PXR5cGUsIHkgPSBuLmJhc2FsKSkgKwogIGdlb21fYm94cGxvdChhZXMoY29sb3I9dHlwZSksbHdkPTEpICt0aGVtZV9jbGFzc2ljKCkrCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yPXR5cGUpLHdpZHRoID0gMC4zLHNpemU9MC4zLGFscGhhID0gMC40ICkrc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15LmNvbFsyOjNdKSt4bGFiKCIiKSt5bGFiKCIjIG9mIEJhc2FsIE5laWdoYm9ycyIpK05vTGVnZW5kKCkrdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMixmYWNlID0gImJvbGQiKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LGhqdXN0PTEsY29sb3IgPSAiYmxhY2siKSxheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplID0gMTUsZmFjZSA9ICJib2xkIikpCmRldi5vZmYoKQpgYGAKCgpgYGB7cn0KCm15X2NvbXBhcmlzb25zIDwtIGxpc3QoICBjKCJCYXNhbCIsICJUcmFuc2l0aW9uX0tDIiksIGMoIlRyYW5zaXRpb25fS0MiLCAiRGlmZmVyZW50aWF0ZWRfS0MiKSAgKQoKI3RpZmYoIn4vT25lRHJpdmUgLSBOb3J0aHdlc3Rlcm4gVW5pdmVyc2l0eS9Ob3J0aHdlc3Rlcm4vWWkgTGFiL01hbnVzY3JpcHQvQ29kZV8ybmREcmFmdC9IdW1hbiBTa2luLy9jbHVzdGVyRGlzdC5CYXNhbC50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NSwgaGVpZ2h0PTUsIHJlcz0zMDApCnNjSG9sb2dyYXBoeTo6Y2x1c3RlckRpc3RhbmNlQm94cGxvdChzY0hvbG9ncmFwaHkub2JqLnN1Yixhbm5vdGF0aW9uVG9Vc2UgPSAic3VwcmFiYXNhbC5zdWIiLHF1ZXJ5LmNsdXN0ZXIubGlzdCA9IGMoIkJhc2FsIiwgIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIpLHJlZmVyZW5jZS5jbHVzdGVyID0gYygiQmFzYWwiKSkrZ2dwbG90Mjo6c2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID1teS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkrTm9MZWdlbmQoKSt0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LGZhY2UgPSAiYm9sZCIpLGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGZhY2UgPSAiYm9sZCIpICxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LGhqdXN0PTEpKQojZGV2Lm9mZigpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpzY0hvbG9ncmFwaHkub2JqLnN1YiRzY0hvbG9ncmFwaHkuc2MgPC0gU2V0SWRlbnQoc2NIb2xvZ3JhcGh5Lm9iai5zdWIkc2NIb2xvZ3JhcGh5LnNjLHZhbHVlID0gInNwYXRpYWwubmVpZ2hib3Job29kIikKCm1hcmsuc3VwIDwtIEZpbmRNYXJrZXJzKHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjLGlkZW50LjEgPSAiRGlmZmVyZW50aWF0ZWRfS0MiLGlkZW50LjIgPSAiVHJhbnNpdGlvbl9LQyIsYXNzYXkgPSAiUk5BIikKCnRvcDEwLnBvcy5zdXA8LSBtYXJrLnN1cCU+JWZpbHRlcihhdmdfbG9nMkZDPjApCndyaXRlLmNzdih0b3AxMC5wb3Muc3VwLCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi9VcFJlZ19pbl9EaWZmZXJlbnRpYXRlZF9LQ19jb21wX3dfVHJhbnNpdGlvbl9LQy5jc3YiKQp0b3AxMC5uZWcuc3VwPC0gbWFyay5zdXAlPiVmaWx0ZXIoYXZnX2xvZzJGQzwwKQp3cml0ZS5jc3YodG9wMTAubmVnLnN1cCwifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzJuZERyYWZ0L0h1bWFuIFNraW4vRG93blJlZ19pbl9EaWZmZXJlbnRpYXRlZF9LQ19jb21wX3dfVHJhbnNpdGlvbl9LQy5jc3YiKQoKbWFyay5iYSA8LSBGaW5kTWFya2VycyhzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyxpZGVudC4xID0gICJUcmFuc2l0aW9uX0tDIixpZGVudC4yID0gIkJhc2FsIiAsYXNzYXkgPSAiUk5BIikKCnRvcDEwLnBvcy5iYTwtIG1hcmsuYmElPiVmaWx0ZXIoYXZnX2xvZzJGQz4wKQp3cml0ZS5jc3YodG9wMTAucG9zLmJhLCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi9VcFJlZ19pbl9UcmFuc2l0aW9uX0tDX2NvbXBfd19CYXNhbC5jc3YiKQp0b3AxMC5uZWcuYmE8LSBtYXJrLmJhJT4lZmlsdGVyKGF2Z19sb2cyRkM8MCkKd3JpdGUuY3N2KHRvcDEwLm5lZy5iYSwifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzJuZERyYWZ0L0h1bWFuIFNraW4vRG93blJlZ19pbl9CYXNhbF9jb21wX3dfVHJhbnNpdGlvbl9LQy5jc3YiKQoKYGBgCgpgYGB7cn0KCiMgVmxuUGxvdChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyxjKCJJVEdCNCIsIkxBTUIzIiwiRFNUIiwiQ09MMTdBMSIpLGlkZW50cyA9IGMoIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIsIkJhc2FsICIpLGFzc2F5ID0gIlNDVCIsbmNvbCA9IDIsY29scyA9IG15LmNvbCkKIyBWbG5QbG90KHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjLGMoIkZBQlA3IiwiVEhFTTUiLCJLUlQxMCIsIkRTRzEiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsbmNvbCA9IDIsY29scyA9IG15LmNvbCkKYGBgCgpgYGB7cn0KbXlfY29tcGFyaXNvbnMgPC0gbGlzdCggYygiQmFzYWwiLCAiVHJhbnNpdGlvbl9LQyIpLCBjKCJUcmFuc2l0aW9uX0tDIiwgIkRpZmZlcmVudGlhdGVkX0tDIikgKQoKdGlmZigifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzNyZERyYWZ0L0VwaXRoZWxpYWwuS1JUNS50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NCwgaGVpZ2h0PTUsIHJlcz0zMDApClZsblBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsYygiS1JUNSIpLGlkZW50cyA9IGMoIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIsIkJhc2FsIiksYXNzYXkgPSAiU0NUIiwgY29scyA9IG15LmNvbCkrIAogIGdlb21fc2lnbmlmKGNvbXBhcmlzb25zID0gbXlfY29tcGFyaXNvbnMsdGVzdC5hcmdzID0gbGlzdChzaXplPTUpLG1hcF9zaWduaWZfbGV2ZWwgPSBUUlVFKSt5bGltKGMoMCw3KSkrTm9MZWdlbmQoKSsgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpKQpkZXYub2ZmKCkKCnRpZmYoIn4vT25lRHJpdmUgLSBOb3J0aHdlc3Rlcm4gVW5pdmVyc2l0eS9Ob3J0aHdlc3Rlcm4vWWkgTGFiL01hbnVzY3JpcHQvQ29kZV8zcmREcmFmdC9FcGl0aGVsaWFsLktSVDE0LnRpZmYiLCB1bml0cz0iaW4iLCB3aWR0aD00LCBoZWlnaHQ9NSwgcmVzPTMwMCkKVmxuUGxvdChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYyxjKCJLUlQxNCIpLGlkZW50cyA9IGMoIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIsIkJhc2FsIiksYXNzYXkgPSAiU0NUIiwgY29scyA9IG15LmNvbCkrIAogIGdlb21fc2lnbmlmKGNvbXBhcmlzb25zID0gbXlfY29tcGFyaXNvbnMsdGVzdC5hcmdzID0gbGlzdChzaXplPTUpLG1hcF9zaWduaWZfbGV2ZWwgPSBUUlVFKSt5bGltKGMoMCw3KSkrTm9MZWdlbmQoKSsgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpKQpkZXYub2ZmKCkKCnRpZmYoIn4vT25lRHJpdmUgLSBOb3J0aHdlc3Rlcm4gVW5pdmVyc2l0eS9Ob3J0aHdlc3Rlcm4vWWkgTGFiL01hbnVzY3JpcHQvQ29kZV8zcmREcmFmdC9FcGl0aGVsaWFsLkNPTDE3QTEudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTQsIGhlaWdodD01LCByZXM9MzAwKQpWbG5QbG90KHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjLGMoIkNPTDE3QTEiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsNSkpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvRXBpdGhlbGlhbC5JVEdBMi50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NCwgaGVpZ2h0PTUsIHJlcz0zMDApClZsblBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsYygiSVRHQTIiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsMy4yNSkpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvRXBpdGhlbGlhbC5JVEdCMS50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NCwgaGVpZ2h0PTUsIHJlcz0zMDApClZsblBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsYygiSVRHQjEiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsMy4yNSkpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvRXBpdGhlbGlhbC5MQU1CMy50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NCwgaGVpZ2h0PTUsIHJlcz0zMDApClZsblBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsYygiTEFNQjMiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsMy43NSkpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgoKCnRpZmYoIn4vT25lRHJpdmUgLSBOb3J0aHdlc3Rlcm4gVW5pdmVyc2l0eS9Ob3J0aHdlc3Rlcm4vWWkgTGFiL01hbnVzY3JpcHQvQ29kZV8zcmREcmFmdC9FcGl0aGVsaWFsLktSVDEudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTQsIGhlaWdodD01LCByZXM9MzAwKQpWbG5QbG90KHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjLGMoIktSVDEiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsNykpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvRXBpdGhlbGlhbC5LUlQxMC50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9NCwgaGVpZ2h0PTUsIHJlcz0zMDApClZsblBsb3Qoc2NIb2xvZ3JhcGh5Lm9iaiRzY0hvbG9ncmFwaHkuc2MsYygiS1JUMTAiKSxpZGVudHMgPSBjKCJUcmFuc2l0aW9uX0tDIiwiRGlmZmVyZW50aWF0ZWRfS0MiLCJCYXNhbCIpLGFzc2F5ID0gIlNDVCIsIGNvbHMgPSBteS5jb2wpKyAKICBnZW9tX3NpZ25pZihjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLHRlc3QuYXJncyA9IGxpc3Qoc2l6ZT01KSxtYXBfc2lnbmlmX2xldmVsID0gVFJVRSkreWxpbShjKDAsNykpK05vTGVnZW5kKCkrIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfM3JkRHJhZnQvRXBpdGhlbGlhbC5LUlREQVAudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTQsIGhlaWdodD01LCByZXM9MzAwKQpWbG5QbG90KHNjSG9sb2dyYXBoeS5vYmokc2NIb2xvZ3JhcGh5LnNjLGMoIktSVERBUCIpLGlkZW50cyA9IGMoIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIsIkJhc2FsIiksYXNzYXkgPSAiU0NUIiwgY29scyA9IG15LmNvbCkrIAogIGdlb21fc2lnbmlmKGNvbXBhcmlzb25zID0gbXlfY29tcGFyaXNvbnMsdGVzdC5hcmdzID0gbGlzdChzaXplPTUpLG1hcF9zaWduaWZfbGV2ZWwgPSBUUlVFKSt5bGltKGMoMCw3KSkrTm9MZWdlbmQoKSsgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpKQpkZXYub2ZmKCkKCmBgYAoKYGBge3J9CgplcGkuc3ViIDwtIHN1YnNldChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYywgY2VsbHMgPSB3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zY0BhY3RpdmUuaWRlbnQlaW4lIGMoIlRyYW5zaXRpb25fS0MiLCJEaWZmZXJlbnRpYXRlZF9LQyIpKSkKRGVmYXVsdEFzc2F5KGVwaS5zdWIpIDwtICJSTkEiCkRvdFBsb3QoZXBpLnN1YixmZWF0dXJlcyA9IGMoIkhTUEcyIiwiQ09MMTdBMSIsIlBER0ZBIiwiSVRHQjEiLCJJVEdBMiIsIkNPTDdBMSIsIklUR0I0IiwiTEFNQjMiLCJEU1QiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiS1JUMSIsIktSVDEwIiwiRFNHMSIsIkVWUEwiLCJQRVJQIiwgI2tlcmF0aW5pemF0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBMQTJHNEYiLCJTVEFSRDEwIiwiUExQUDIiLCJST1JBIiwiSE1HQ1IiLCJGQUJQNyIsIkRCSSIsIlRIRU01IiwiRVBIWDIiLCJQVEdTMSIsIkdTVEE0IiApLGFzc2F5ID0gIlNDVCIpK3ZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMoKStnZ3Bsb3QyOjpjb29yZF9mbGlwKCkrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKQoKdGlmZigifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzJuZERyYWZ0L0h1bWFuIFNraW4vL0RvdFBsb3QudHJhbnMudnMuZGlmZi50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9MywgaGVpZ2h0PTEwLCByZXM9MzAwKQpEb3RQbG90KGVwaS5zdWIsZmVhdHVyZXMgPSBjKHJvd25hbWVzKG1hcmsuc3VwICU+JXRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nMkZDKSApLHJvd25hbWVzKG1hcmsuc3VwICU+JXRvcF9uKG4gPSAxMCwgd3QgPSAtYXZnX2xvZzJGQykgKSksYXNzYXkgPSAiU0NUIikrdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcygpK2dncGxvdDI6OmNvb3JkX2ZsaXAoKSsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3Q9MSkpK3RoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkrTm9MZWdlbmQoKQpkZXYub2ZmKCkKYGBgCmBgYHtyfQplcGkuc3ViIDwtIHN1YnNldChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYywgY2VsbHMgPSB3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zY0BhY3RpdmUuaWRlbnQlaW4lIGMoIlRyYW5zaXRpb25fS0MiLCJCYXNhbCIpKSkKRGVmYXVsdEFzc2F5KGVwaS5zdWIpIDwtICJSTkEiCkRvdFBsb3QoZXBpLnN1YixmZWF0dXJlcyA9IGMoIkFOWEExIiwiQ0xTVE4xIiwiRFVTUDYiLCJQVFBSWjEiLCJNRUYyQSIsICNzaWduYWwgdHJhbnNkdWN0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNPTDE3QTEiLCJQREdGQSIsIklUR0IxIiwiQ09MNEE1IiwiQ09MN0ExIiwiSVRHQjQiLCJMQU1CMyIsIkRTVCIsICNleHRyYWNlbGx1bGFyIG1hdHJpeAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU0cxIiwiS1JUMSIsIktSVDEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVDVElOMSIsIk5FQ1RJTjQiLCJDTERONCIsIkNMRE4xIgopLGFzc2F5ID0gIlNDVCIpK3ZpcmlkaXM6OnNjYWxlX2NvbG9yX3ZpcmlkaXMoKStnZ3Bsb3QyOjpjb29yZF9mbGlwKCkrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpKQoKdGlmZigifi9PbmVEcml2ZSAtIE5vcnRod2VzdGVybiBVbml2ZXJzaXR5L05vcnRod2VzdGVybi9ZaSBMYWIvTWFudXNjcmlwdC9Db2RlXzJuZERyYWZ0L0h1bWFuIFNraW4vL0RvdFBsb3QudHJhbnMudnMuYmFzYWwudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTMsIGhlaWdodD0xMCwgcmVzPTMwMCkKRG90UGxvdChlcGkuc3ViLGZlYXR1cmVzID0gYyhyb3duYW1lcyhtYXJrLmJhICU+JXRvcF9uKG4gPSAxMCwgd3QgPSBhdmdfbG9nMkZDKSApLHJvd25hbWVzKG1hcmsuYmEgJT4ldG9wX24obiA9IDEwLCB3dCA9IC1hdmdfbG9nMkZDKSApKSxhc3NheSA9ICJTQ1QiKSt2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKCkrZ2dwbG90Mjo6Y29vcmRfZmxpcCgpKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkrdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpKStOb0xlZ2VuZCgpCmRldi5vZmYoKQpgYGAKCgoKCmBgYHtyfQpsaWJyYXJ5KENlbGxDaGF0KQplcGkuc3ViIDwtIHN1YnNldChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zYywgY2VsbHMgPSB3aGljaChzY0hvbG9ncmFwaHkub2JqJHNjSG9sb2dyYXBoeS5zY0BhY3RpdmUuaWRlbnQlaW4lIGMoIlRyYW5zaXRpb25fS0MiLCJCYXNhbCIsIkRpZmZlcmVudGlhdGVkX0tDIikpKQplcGkuc3ViJHN1cHJhYmFzYWwuc3ViIDwtIGRyb3BsZXZlbHMoZXBpLnN1YiRzdXByYWJhc2FsLnN1YiApCmNlbGxjaGF0Lm9iaiA8LSBjcmVhdGVDZWxsQ2hhdChlcGkuc3ViLGdyb3VwLmJ5ID0gInN1cHJhYmFzYWwuc3ViIixhc3NheSA9ICJTQ1QiKQpDZWxsQ2hhdERCIDwtIENlbGxDaGF0REIuaHVtYW4KQ2VsbENoYXREQi51c2UgPC0gQ2VsbENoYXREQiAKY2VsbGNoYXQub2JqQERCIDwtIENlbGxDaGF0REIudXNlCmNlbGxjaGF0Lm9iaiA8LSBzdWJzZXREYXRhKGNlbGxjaGF0Lm9iaikKY2VsbGNoYXQub2JqIDwtIGlkZW50aWZ5T3ZlckV4cHJlc3NlZEdlbmVzKGNlbGxjaGF0Lm9iaikKY2VsbGNoYXQub2JqIDwtIGlkZW50aWZ5T3ZlckV4cHJlc3NlZEludGVyYWN0aW9ucyhjZWxsY2hhdC5vYmopCmBgYApgYGB7cn0KY2VsbGNoYXQub2JqIDwtIGNvbXB1dGVDb21tdW5Qcm9iKGNlbGxjaGF0Lm9iaikKIyBGaWx0ZXIgb3V0IHRoZSBjZWxsLWNlbGwgY29tbXVuaWNhdGlvbiBpZiB0aGVyZSBhcmUgb25seSBmZXcgbnVtYmVyIG9mIGNlbGxzIGluIGNlcnRhaW4gY2VsbCBncm91cHMKY2VsbGNoYXQub2JqIDwtIGZpbHRlckNvbW11bmljYXRpb24oY2VsbGNoYXQub2JqLCBtaW4uY2VsbHMgPSAxMCkKY2VsbGNoYXQub2JqIDwtIGNvbXB1dGVDb21tdW5Qcm9iUGF0aHdheShjZWxsY2hhdC5vYmopCmNlbGxjaGF0Lm9iaiA8LSBhZ2dyZWdhdGVOZXQoY2VsbGNoYXQub2JqKQpgYGAKYGBge3J9CmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKY2VsbGNoYXQub2JqIDwtIG5ldEFuYWx5c2lzX2NvbXB1dGVDZW50cmFsaXR5KGNlbGxjaGF0Lm9iaiwgc2xvdC5uYW1lID0gIm5ldFAiKSAKbXkuc2lnIDwtIGMoIkxBTUlOSU4iLCJUSEJTIiwiREVTTU9TT01FIiwiTkVDVElOIiwiTk9UQ0giLCJFR0YiLCJOUkciKQp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi8vRXBpdGhlbGlhbC5jZWxsY2hhdC5vdXQudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTksIGhlaWdodD02LCByZXM9MzAwKQpuZXRBbmFseXNpc19zaWduYWxpbmdSb2xlX2hlYXRtYXAoY2VsbGNoYXQub2JqLCBwYXR0ZXJuID0gIm91dGdvaW5nIix3aWR0aCA9IDksaGVpZ2h0ID0gNixmb250LnNpemUgPSAxNSxjb2xvci5oZWF0bWFwID0gIllsT3JSZCIsc2lnbmFsaW5nID1teS5zaWcsY29sb3IudXNlID0gbXkuY29sICkKZGV2Lm9mZigpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi8vRXBpdGhlbGlhbC5jZWxsY2hhdC5pbi50aWZmIiwgdW5pdHM9ImluIiwgd2lkdGg9OSwgaGVpZ2h0PTYsIHJlcz0zMDApCm5ldEFuYWx5c2lzX3NpZ25hbGluZ1JvbGVfaGVhdG1hcChjZWxsY2hhdC5vYmosIHBhdHRlcm4gPSAiaW5jb21pbmciLHdpZHRoID0gOSxoZWlnaHQgPSA2LGZvbnQuc2l6ZSA9IDE1LGNvbG9yLmhlYXRtYXAgPSAiWWxPclJkIixzaWduYWxpbmcgPW15LnNpZyxjb2xvci51c2UgPSBteS5jb2wgICkKZGV2Lm9mZigpCmBgYAoKCmBgYHtyfQpSZWFjdG9tZV8yMDIyX2hpZ2hfZGlmZiA8LSByZWFkLmRlbGltKCJ+L0xpYnJhcnkvQ2xvdWRTdG9yYWdlL09uZURyaXZlLU5vcnRod2VzdGVyblVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi9SZWFjdG9tZV8yMDIyX0hJR0hfaW5fZGlmZl9rYy50eHQiLCBxdW90ZT0iIikKUmVhY3RvbWVfMjAyMl9oaWdoX2RpZmYuc3ViIDwtIFJlYWN0b21lXzIwMjJfaGlnaF9kaWZmWzE6NSxdClJlYWN0b21lXzIwMjJfaGlnaF9kaWZmLnN1YiRUZXJtIDwtIHVubGlzdChsYXBwbHkoUmVhY3RvbWVfMjAyMl9oaWdoX2RpZmYuc3ViJFRlcm0gLCBmdW5jdGlvbih4KSBzdHJzcGxpdCh4LCIgUi1IU0EiKVtbMV1dWzFdKSkKUmVhY3RvbWVfMjAyMl9oaWdoX2RpZmYuc3ViJFRlcm0gPC0gZmFjdG9yKFJlYWN0b21lXzIwMjJfaGlnaF9kaWZmLnN1YiRUZXJtLGxldmVscyA9IHJldihSZWFjdG9tZV8yMDIyX2hpZ2hfZGlmZi5zdWIkVGVybSkpCgp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi8vUmVhY3RvbWVfMjAyMl9oaWdoX2RpZmYudGlmZiIsIHVuaXRzPSJpbiIsIHdpZHRoPTYsIGhlaWdodD02LCByZXM9MzAwKQpnZ3Bsb3QoZGF0YT1SZWFjdG9tZV8yMDIyX2hpZ2hfZGlmZi5zdWIsIGFlcyh4PVRlcm0sIHk9LWxvZyhBZGp1c3RlZC5QLnZhbHVlKSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD1teS5jb2xbM10pICsgY29vcmRfZmxpcCgpK3RoZW1lX2NsYXNzaWMoKSt0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSxheGlzLnRpdGxlICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsZmFjZSA9ICJib2xkIikpCmRldi5vZmYoKQoKCgpnZ3Bsb3QoZGF0YT1SZWFjdG9tZV8yMDIyX2hpZ2hfZGlmZi5zdWIsIGFlcyh4PVRlcm0sIHk9LWxvZyhBZGp1c3RlZC5QLnZhbHVlKSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD1teS5jb2xbM10pICsgY29vcmRfZmxpcCgpK3RoZW1lX2NsYXNzaWMoKSt0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSxheGlzLnRpdGxlICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsZmFjZSA9ICJib2xkIikpK2dlb21fdGV4dChhZXMobGFiZWw9R2VuZXMpLCB5PWMoMCksaGp1c3QgPSAwLGNvbG9yPSJ3aGl0ZSIsIHNpemU9YygxLjc1LDIuMjUsMi41LDIuNSwyLjUpKSt0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkpCmBgYApgYGB7cn0KIyMjIFJ1biBSZWF0b21lIDIwMjIgb24gZ2VuZXMgd2l0aCA8MC4wNSBhZGp1c3RlZCBwIHZhbHVlcyBpbiBVcFJlZ19pbl9EaWZmZXJlbnRpYXRlZF9LQ19jb21wX3dfVHJhbnNpdGlvbl9LQy5jc3YgYW5kIFVwUmVnX2luX1RyYW5zaXRpb25fS0NfY29tcF93X0Jhc2FsLmNzdgoKUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zIDwtIHJlYWQuZGVsaW0oIn4vTGlicmFyeS9DbG91ZFN0b3JhZ2UvT25lRHJpdmUtTm9ydGh3ZXN0ZXJuVW5pdmVyc2l0eS9Ob3J0aHdlc3Rlcm4vWWkgTGFiL01hbnVzY3JpcHQvQ29kZV8ybmREcmFmdC9IdW1hbiBTa2luL1JlYWN0b21lXzIwMjJfSElHSF9pbl90cmFucy50eHQiLCBxdW90ZT0iIikKUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiA8LSBSZWFjdG9tZV8yMDIyX2hpZ2hfdHJhbnNbMTo1LF0KUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiRUZXJtIDwtIHVubGlzdChsYXBwbHkoUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiRUZXJtICwgZnVuY3Rpb24oeCkgc3Ryc3BsaXQoeCwiIFItSFNBIilbWzFdXVsxXSkpClJlYWN0b21lXzIwMjJfaGlnaF90cmFucy5zdWIkVGVybSA8LSBmYWN0b3IoUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiRUZXJtLGxldmVscyA9IHJldihSZWFjdG9tZV8yMDIyX2hpZ2hfdHJhbnMuc3ViJFRlcm0pKQp0aWZmKCJ+L09uZURyaXZlIC0gTm9ydGh3ZXN0ZXJuIFVuaXZlcnNpdHkvTm9ydGh3ZXN0ZXJuL1lpIExhYi9NYW51c2NyaXB0L0NvZGVfMm5kRHJhZnQvSHVtYW4gU2tpbi8vUmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnRpZmYiLCB1bml0cz0iaW4iLCB3aWR0aD02LCBoZWlnaHQ9NiwgcmVzPTMwMCkKZ2dwbG90KGRhdGE9UmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiwgYWVzKHg9VGVybSwgeT0tbG9nKEFkanVzdGVkLlAudmFsdWUpKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixmaWxsPW15LmNvbFsyXSkgKyBjb29yZF9mbGlwKCkrdGhlbWVfY2xhc3NpYygpK3RoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpLGF4aXMudGl0bGUgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkKZGV2Lm9mZigpCgoKZ2dwbG90KGRhdGE9UmVhY3RvbWVfMjAyMl9oaWdoX3RyYW5zLnN1YiwgYWVzKHg9VGVybSwgeT0tbG9nKEFkanVzdGVkLlAudmFsdWUpKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IixmaWxsPW15LmNvbFsyXSkgKyBjb29yZF9mbGlwKCkrdGhlbWVfY2xhc3NpYygpK3RoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGZhY2UgPSAiYm9sZCIpLGF4aXMudGl0bGUgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxmYWNlID0gImJvbGQiKSkrdGhlbWVfY2xhc3NpYygpK2dlb21fdGV4dChhZXMobGFiZWw9R2VuZXMpLCB5PWMoMCksaGp1c3QgPSAwLGNvbG9yPSJ3aGl0ZSIsIHNpemU9YygyLjUsMi41LDIuNSwyLjUsMi41KSkrdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCgoK